package  
{
  import com.bit101.components.CheckBox;
  import com.bit101.components.ColorChooser;
  import com.bit101.components.ComboBox;
  import com.bit101.components.FPSMeter;
  import com.bit101.components.HUISlider;
  import com.bit101.components.Label;
  import com.bit101.components.Panel;
  import com.bit101.components.PushButton;
  import flash.display.BitmapData;
  import flash.display.Loader;
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.net.FileFilter;
  import flash.net.FileReference;
  import flash.utils.ByteArray;
  import mge.particles.Descriptor;
  import mge.particles.ParticleSystem;
  import mge.serialization.Serializer;
	/**
   * ...
   * @author ivan
   */
  public class ParticleEditor 
  {
    
    public function ParticleEditor(parent:Sprite, particleSystem:ParticleSystem) 
    {
      this.particleSystem = particleSystem;
      
      leftPanel = new Panel(parent, 0, 0);
      leftPanel.width = 200;
      leftPanel.height = 800;
      
      rightPanel = new Panel(parent, 500, 0);
      rightPanel.width = 200;
      rightPanel.height = 800;
      
      new FPSMeter(parent, 10, 10);
      
      /**
       * System parameters
       *************************************************************************/
      systemLifeTimeSlider = new HUISlider(leftPanel, 10, 30, "System Life Time", onSystemLifeTime);
      systemLifeTimeSlider.setSliderParams(0, 5, 1);
      systemLifeTimeSlider.labelPrecision = 2;
      
      emissionSlider = new HUISlider(leftPanel, 10, 50, "Emission", onEmission);
      emissionSlider.setSliderParams(1, 150, 0);
      emissionSlider.labelPrecision = 0;
      
      continuousCheckbox = new CheckBox(leftPanel, 30, 70, "Continuous", onContinuous);
      
      particleLifeTimeMax = new HUISlider(leftPanel, 10, 90, "Part life time max", onParticleLifeTimeMax);
      particleLifeTimeMax.setSliderParams(0, 5, 1);
      
      particleLifeTimeMin = new HUISlider(leftPanel, 10, 110, "Part life time min", onParticleLifeTimeMin);
      particleLifeTimeMin.setSliderParams(0, 5, 1);
      
      
      /**
       * Particle movement
       *************************************************************************/
      new Label(leftPanel, 5, 140, "Radial Acceleration");
      
      radialAccelerationMax = new HUISlider(leftPanel, 10, 155, "max", onRadialAccelerationMax);
      radialAccelerationMax.setSliderParams( -2.5, 2.5, 0);
      
      radialAccelerationMin = new HUISlider(leftPanel, 10, 170, "min", onRadialAccelerationMin);
      radialAccelerationMin.setSliderParams(-2.5, 2.5, 0);
      
      new Label(leftPanel, 5, 200, "Gravity");
      
      gravityMax = new HUISlider(leftPanel, 10, 215, "max", onGravityMax);
      gravityMax.setSliderParams( -1000, 1000, 0);
      
      gravityMin = new HUISlider(leftPanel, 10, 230, "min", onGravityMin);
      gravityMin.setSliderParams( -1000, 1000, 0);
      
      
      new Label(leftPanel, 5, 260, "Velocity");
      
      velocityMax = new HUISlider(leftPanel, 10, 275, "max", onVelocityMax);
      velocityMax.setSliderParams( -1000, 1000, 0);
      
      velocityMin = new HUISlider(leftPanel, 10, 290, "min", onVelocityMin);
      velocityMin.setSliderParams( -1000, 1000, 0);
      
      new Label(leftPanel, 5, 320, "Spread");
      
      spread = new HUISlider(leftPanel, 10, 335, "", onSpread);
      spread.setSliderParams( 0, 360, 360);
      
      
      /**
      * Particle appareance
      *************************************************************************/
      new Label(rightPanel, 5, 10, "Scale");
      
      scaleStart = new HUISlider(rightPanel, 10, 25, "start", onScaleStart);
      scaleStart.setSliderParams( 0, 3, 3);
      
      scaleEnd = new HUISlider(rightPanel, 10, 40, "end", onScaleEnd);
      scaleEnd.setSliderParams( 0, 3, 2.9);
      
      scaleVar = new HUISlider(rightPanel, 10, 55, "var", onScaleVar);
      scaleVar.setSliderParams( 0, 3, 0);
      
      new Label(rightPanel, 5, 80, "Spin");
      
      spinStart = new HUISlider(rightPanel, 10, 95, "start", onSpinStart);
      spinStart.setSliderParams( -20, 20, 1);
      
      spinEnd = new HUISlider(rightPanel, 10, 110, "end", onSpinEnd);
      spinEnd.setSliderParams( -20, 20, 0);
      
      spinVar = new HUISlider(rightPanel, 10, 125, "var", onSpinVar);
      spinVar.setSliderParams( 0, 20, 0);

      
      new Label(rightPanel, 5, 150, "Color Start");
      colorStart = new ColorChooser(rightPanel, 80, 170, 0xffffff, onColorStart);
      colorStart.usePopup = true;
      
      alphaStart = new HUISlider(rightPanel, 10, 190, "alpha", onAlphaStart);
      alphaStart.setSliderParams( 0, 255, 255);
      alphaStart.labelPrecision = 0;
      
      
      new Label(rightPanel, 5, 210, "Color End");
      
      colorEnd = new ColorChooser(rightPanel, 80, 230, 0xffffff, onColorEnd);
      colorEnd.usePopup = true;
      
      alphaEnd = new HUISlider(rightPanel, 10, 250, "alpha", onAlphaEnd);
      alphaEnd.setSliderParams( 0, 255, 255);
      alphaEnd.labelPrecision = 0;
      
      new Label(rightPanel, 5, 280, "Bitmap");
      
      var array:Array = new Array("circle logarithmic", "shine cross", "fire", "smoke", "particles", "star", "spark", "bubble", "spark minimal", "spark empty", "spark fill", "small bubble", "spark electric", "circle filled", "circle void", "Z");
      bitmapIndex = new ComboBox(rightPanel, 50, 300, "", array);
      bitmapIndex.selectedIndex = 0;
      bitmapIndex.addEventListener(Event.SELECT, onBitmapIndex);
      //bitmapIndex.setSliderParams( 0, 15, 0);
      //bitmapIndex.labelPrecision = 0;
      
      new PushButton(rightPanel, 0, 330, "Export", onExportClick);
            
      new PushButton(rightPanel, 100, 330, "Import", load);
      
      new PushButton(rightPanel, 0, 350, "Background", loadBackground);
      
      
      initSystemParams();
    }
    
    private function initSystemParams():void
    {
        onSystemLifeTime(null);
        onEmission(null);
        onContinuous(null);
        onParticleLifeTimeMax(null);
        onParticleLifeTimeMin(null);
        
        onRadialAccelerationMax(null);
        onRadialAccelerationMin(null);
        onGravityMax(null);
        onGravityMin(null);
        onVelocityMax(null);
        onVelocityMin(null);
        onSpread(null);
        
        onScaleStart(null);
        onScaleEnd(null);
        onScaleVar(null);
        onSpinStart(null);
        onSpinEnd(null);
        onSpinVar(null);
        onColorStart(null);
        onColorEnd(null);
    }
    
    /**
     * System parameters
     *************************************************************************/
    private var systemLifeTimeSlider:HUISlider;
    private var emissionSlider:HUISlider;    
    private var continuousCheckbox:CheckBox;
    private var particleLifeTimeMax:HUISlider;
    private var particleLifeTimeMin:HUISlider;
    
    private function onSystemLifeTime(e:Event):void { particleSystem.descriptor.systemLifeTime = systemLifeTimeSlider.value; }
    private function onEmission(e:Event):void { particleSystem.descriptor.emission = emissionSlider.value; }
    private function onContinuous(e:Event):void { particleSystem.descriptor.continuous = continuousCheckbox.selected; }
    private function onParticleLifeTimeMax(e:Event):void { particleSystem.descriptor.particleLifeTimeMax = particleLifeTimeMax.value; }
    private function onParticleLifeTimeMin(e:Event):void { particleSystem.descriptor.particleLifeTimeMin = particleLifeTimeMin.value; }
    
    
    /**
     * Particle movement
     *************************************************************************/
    private var radialAccelerationMax:HUISlider;
    private var radialAccelerationMin:HUISlider;
    private var gravityMax:HUISlider;
    private var gravityMin:HUISlider;
    private var velocityMax:HUISlider;
    private var velocityMin:HUISlider;
    private var spread:HUISlider;
    
    private function onRadialAccelerationMax(e:Event):void { particleSystem.descriptor.radialAccelerationMax = radialAccelerationMax.value; }
    private function onRadialAccelerationMin(e:Event):void { particleSystem.descriptor.radialAccelerationMin= radialAccelerationMin.value; }
    private function onGravityMax(e:Event):void { particleSystem.descriptor.gravityMax= gravityMax.value; }
    private function onGravityMin(e:Event):void { particleSystem.descriptor.gravityMin= gravityMin.value; }
    private function onVelocityMax(e:Event):void { particleSystem.descriptor.velocityMax = velocityMax.value; }
    private function onVelocityMin(e:Event):void { particleSystem.descriptor.velocityMin= velocityMin.value; }
    private function onSpread(e:Event):void { particleSystem.descriptor.spread = spread.value; }

     
    /**
     * Particle appareance
     *************************************************************************/
    private var bitmapIndex:ComboBox;
    
    private var scaleStart:HUISlider;
    private var scaleEnd:HUISlider;
    private var scaleVar:HUISlider;
    
    private var spinStart:HUISlider;
    private var spinEnd:HUISlider;
    private var spinVar:HUISlider;
    
    private var colorStart:ColorChooser;
    private var alphaStart:HUISlider;
    
    private var colorEnd:ColorChooser;
    private var alphaEnd:HUISlider;
    
    private function onBitmapIndex(e:Event):void { particleSystem.descriptor.bitmapIndex = bitmapIndex.selectedIndex; particleSystem.descriptor = particleSystem.descriptor;  }
    private function onScaleStart(e:Event):void { particleSystem.descriptor.scaleStart = scaleStart.value; }
    private function onScaleEnd(e:Event):void { particleSystem.descriptor.scaleEnd = scaleEnd.value; }
    private function onScaleVar(e:Event):void { particleSystem.descriptor.scaleVar = scaleVar.value; }
    
    private function onColorStart(e:Event):void { particleSystem.descriptor.colorStart = (colorStart.value | alphaStart.value << 24); }
    private function onAlphaStart(e:Event):void { particleSystem.descriptor.colorStart = (colorStart.value | alphaStart.value << 24); }
    
    private function onColorEnd(e:Event):void { particleSystem.descriptor.colorEnd =     (colorEnd.value | alphaEnd.value << 24); }
    private function onAlphaEnd(e:Event):void { particleSystem.descriptor.colorEnd =     (colorEnd.value | alphaEnd.value << 24); }
    
    private function onSpinStart(e:Event):void { particleSystem.descriptor.spinStart = spinStart.value; }
    private function onSpinEnd(e:Event):void { particleSystem.descriptor.spinEnd = spinEnd.value; }
    private function onSpinVar(e:Event):void { particleSystem.descriptor.spinVar = spinVar.value; }
    
    /**
     * Other
     *************************************************************************/
    private function onExportClick(e:Event):void
    {
      // Opens a dialog to save file.
      var xml:XML = new Serializer().serialize(particleSystem.descriptor);
        
      var ba:ByteArray = new ByteArray();
      ba.writeUTFBytes(xml);
      var fr:FileReference = new FileReference();
      fr.save(ba, "ps.xml");
    }
        
    private var file:FileReference;
    public function load(e:Event):void
    {
      file = new FileReference();
      file.browse(new Array(new FileFilter("XML files (*.xml)", "*.xml"), new FileFilter("All (*.*)", "*.*")));
      file.addEventListener(Event.SELECT, _selectFile);
    }
    
    private function _selectFile(e:Event):void
    {
      file.addEventListener(Event.COMPLETE, _loadFile);
      file.load();
    }
    
    private function _loadFile(e:Event):void
    {
      var xml:XML = new XML(file.data);
      var d:Descriptor = new Serializer().deserialize(xml, Descriptor) as Descriptor;
      particleSystem.descriptor = d;      
      file = null;
      
      mapDescriptorToControls();
    }
    
    private function mapDescriptorToControls():void
    {
      var d:Descriptor = particleSystem._descriptor;
      
      // System parameters
      systemLifeTimeSlider.value = d.systemLifeTime;
      emissionSlider.value = d.emission;
      continuousCheckbox.selected = d.continuous;
      particleLifeTimeMax.value = d.particleLifeTimeMax;
      particleLifeTimeMin.value = d.particleLifeTimeMin;
      
      // Particle movement
      radialAccelerationMax.value = d.radialAccelerationMax;
      radialAccelerationMin.value = d.radialAccelerationMin;
      gravityMax.value = d.gravityMax;
      gravityMin.value = d.gravityMin;
      velocityMax.value = d.velocityMax;
      velocityMin.value = d.velocityMin;
      spread.value = d.spread;
      
      // Particle appareance      
      bitmapIndex.selectedIndex = d.bitmapIndex;      
      scaleStart.value = d.scaleStart;
      scaleEnd.value = d.scaleEnd;
      scaleVar.value = d.scaleVar;
      spinStart.value = d.spinStart;
      spinEnd.value = d.spinEnd;
      spinVar.value = d.spinVar;
      colorStart.value = d.colorStart & 0x00FFFFFF;
      alphaStart.value = (uint)(d.colorStart >> 24);
      colorEnd.value = d.colorEnd & 0x00FFFFFF;
      alphaEnd.value = (uint)(d.colorEnd >> 24);
    }
    
    
    public function loadBackground(e:Event):void
    {
      file = new FileReference();
      file.browse(new Array(new FileFilter("Image files", "*.jpg;*.gif;*.png"), new FileFilter("All (*.*)", "*.*")));
      file.addEventListener(Event.SELECT, _selectBackground);
    }
    
    private function _selectBackground(e:Event):void
    {
      file.addEventListener(Event.COMPLETE, _loadBackground);
      file.load();
    }
    
    private function _loadBackground(e:Event):void
    {
      var loader:Loader = new Loader();
      loader.loadBytes(file.data);
      
      while (Main.background.numChildren > 0)
        Main.background.removeChildAt(0);
        
      Main.background.addChild(loader);
      
      file = null;
    }
    
    private var particleSystem:ParticleSystem;
    private var leftPanel:Panel;
    private var rightPanel:Panel;
    
    
    
    
  }

}